﻿
#include <windows.h>
#include "CBaseWin.h"
#include <assert.h>
#include <WindowsX.h>
#include "Resource.h"
#include <string>
#include <iostream>

extern HMODULE GetModule();
using namespace std;
std::map<HWND, void*> CBaseWnd::ms_windows;

CBaseWnd::CBaseWnd()
{
	m_hWnd = 0;
	m_bFullScreen = FALSE;
	m_winStyle = WINDOW_STYLE;
	m_fullStyle = WINDOW_STYLE_FULLSCREEN;
	m_winStyleEx = WS_EX_APPWINDOW;

	m_preMouseX = 0;
	m_preMouseY = 0;
	m_isMouseInWindow = FALSE;
	m_bFullScreen = FALSE;

	m_hCurrentCursor = m_hArror = ::LoadCursor(NULL, IDC_ARROW);
	m_hCross = ::LoadCursor(NULL, IDC_CROSS);
	m_hHand = ::LoadCursor(NULL, IDC_HAND);
	m_hSizeWE = ::LoadCursor(NULL, IDC_SIZEWE);
	m_hSizeNS = ::LoadCursor(NULL, IDC_SIZENS);
	m_hSizeNWSE = ::LoadCursor(NULL, IDC_SIZENWSE);
	m_hSizeNESW = ::LoadCursor(NULL, IDC_SIZENESW);
	m_hSizeAll = ::LoadCursor(NULL, IDC_SIZEALL);
	m_hQuery = ::LoadCursor(NULL, IDC_NO);
	m_hDrop = ::LoadCursor(GetModule(),  MAKEINTRESOURCE(IDC_CURSOR_Drop));
}

CBaseWnd::~CBaseWnd()
{
	::DestroyCursor(m_hArror);
	::DestroyCursor(m_hCross);
	::DestroyCursor(m_hHand);
	::DestroyCursor(m_hQuery);
	::DestroyCursor(m_hDrop);
	::DestroyCursor(m_hSizeWE);
	::DestroyCursor(m_hSizeNS);
	::DestroyCursor(m_hSizeNWSE);
	::DestroyCursor(m_hSizeNESW);
	::DestroyCursor(m_hSizeAll);
	for(	std::map<std::wstring, HCURSOR>::iterator itr = m_mapCursors.begin();
		itr != m_mapCursors.end();
		++itr )
	{
		::DestroyCursor((*itr).second);
	}
}
HRESULT CBaseWnd::_GetWndClassName(WCHAR* wndClassName, UINT szSize, UINT wstyle)
{
	if (wndClassName == NULL || szSize <= 0)
		return E_FAIL;

	swprintf_s(wndClassName, szSize, L"CBaseWnd_%d", wstyle);
	return S_OK;
}

ATOM CBaseWnd::_RegisterWndClass(HINSTANCE hInstance, UINT wstyle)
{
	WNDCLASSEX wcex;	
	WCHAR wndClassName[MAX_PATH] = {0};
	_GetWndClassName(wndClassName, MAX_PATH, wstyle);

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style			= wstyle;
	wcex.lpfnWndProc	= GetWndProc();
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= NULL;
	wcex.hCursor		= ::LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= wndClassName;
	wcex.hIconSm		= NULL;
	ATOM ret = RegisterClassEx(&wcex);

	return ret;
}

HRESULT CBaseWnd::_CreateWindow(HWND hWndParent, UINT wndWidth, UINT wndHeight, HWND& hwnd, const WCHAR* pWndName, UINT classStyle, UINT windowStyle, UINT windowExStyle, int winPosX, int winPosY)
{
	WCHAR wndName[MAX_PATH] = {0};
	if (pWndName == NULL)
	{
		swprintf_s(wndName, MAX_PATH, L"CBaseWnd");
	}
	else
	{
		wcscpy_s(wndName, MAX_PATH, pWndName);
	}
	WCHAR wndClassName[MAX_PATH] = {0};
	_GetWndClassName(wndClassName, MAX_PATH, classStyle);
	if (wndWidth != 0 && wndWidth != 0)
	{
		hwnd = CreateWindowExW(windowExStyle, wndClassName, wndName, windowStyle,
			winPosX, winPosY, wndWidth, wndHeight, hWndParent, NULL, GetModule(), NULL);
	}
	else
	{
		hwnd = CreateWindowExW(windowExStyle, wndClassName, wndName, windowStyle,
			winPosX, winPosY, CW_USEDEFAULT, 0, hWndParent, NULL, GetModule(), NULL);		
	}
	m_winStyle = windowStyle;
	m_winStyleEx = windowExStyle;
	
	return S_OK;
}

HRESULT CBaseWnd::ShowWindow(UINT cmdShow)
{
	if (m_hWnd == 0)
	{
		return S_FALSE;
	}
	::ShowWindow(m_hWnd, cmdShow);
	return S_OK;
}
int CBaseWnd::GetHwnd()
{
	return (long)m_hWnd;
}
HRESULT CBaseWnd::ResizeWindow(UINT width, UINT height)
{
	if (m_hWnd == 0)
		return E_FAIL;
	RECT rect;
	BOOL ret = ::GetWindowRect(m_hWnd, &rect);
	if (!ret)
		return E_FAIL;
	ret = ::SetWindowPos(m_hWnd, HWND_NOTOPMOST, rect.left, rect.top, width, height, SWP_NOZORDER);
	if (!ret)
		return E_FAIL;
	return S_OK;
}
HRESULT CBaseWnd::_TrackMouseLeave()
{
	if (this->m_hWnd == 0)
	{
		assert(0);
		return E_FAIL;
	}
	TRACKMOUSEEVENT trackInfo;
	trackInfo.cbSize = sizeof(TRACKMOUSEEVENT);
	trackInfo.hwndTrack = this->m_hWnd;
	trackInfo.dwFlags = TME_LEAVE;
	trackInfo.dwHoverTime = 1000;
	TrackMouseEvent(&trackInfo);
	return S_OK;
}
HRESULT CBaseWnd::Create(HWND hwndParent, UINT wndWidth, UINT wndHeight, const WCHAR* pWndName, UINT classStyle, UINT windowStyle, UINT windowExStyle, int winPosX, int winPosY)
{
	HRESULT hr = S_OK;
	if (m_hWnd != 0)
	{
		::DestroyWindow(m_hWnd);
		m_hWnd = 0;
	}

	if (FAILED(this->_RegisterWndClass(GetModule(), classStyle)))
		return E_FAIL;
	if (FAILED(this->_CreateWindow(hwndParent, wndWidth, wndHeight, m_hWnd, pWndName, classStyle, windowStyle,  windowExStyle, winPosX, winPosY)))
		return E_FAIL;
	ms_windows[m_hWnd] = (void*)(CBaseWnd*)this;

	
	return S_OK;
}
HRESULT CBaseWnd::DestroyWindow()
{
	if (m_hWnd == NULL)
		return E_FAIL;
	::DestroyWindow(m_hWnd);
	ms_windows.erase(m_hWnd);
	return S_OK;
}
BOOL CBaseWnd::IsWindowVisible()
{
	if (m_hWnd == NULL)
		return FALSE;
	return ::IsWindowVisible(m_hWnd);
}


WNDPROC CBaseWnd::GetWndProc()
{
	return CBaseWnd::_WndProc;
}
LRESULT CBaseWnd::_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HRESULT hr = S_OK;
	std::map<HWND, void*>::iterator iter = ms_windows.find(hWnd);
	if (iter == ms_windows.end())
	{
		//assert(0);
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	CBaseWnd* pThis = (CBaseWnd*) iter->second;
	return pThis->WndProc(hWnd, message, wParam, lParam);
}

BOOL CBaseWnd::GetWindowRect(RECT* rect)
{
	if (m_hWnd == 0)
		return FALSE;
	return ::GetWindowRect(m_hWnd, rect);
}
BOOL CBaseWnd::GetClientRect(RECT* rect)
{
	if (m_hWnd == 0)
		return FALSE;
	return ::GetClientRect(m_hWnd, rect);
}

BOOL CBaseWnd::ScreenToClient(int& outX, int& outY, int x, int y)
{
	if (m_hWnd == 0)
		return FALSE;
	BOOL ret = TRUE;
	POINT pt;
	pt.x = x;
	pt.y = y;
	ret = ::ScreenToClient(m_hWnd, &pt);
	outX = pt.x;
	outY = pt.y;
	return ret;

}
BOOL CBaseWnd::ClientToScreen(int& outX, int& outY, int x, int y)
{
	if (m_hWnd == 0)
		return FALSE;
	BOOL ret = TRUE;
	POINT pt;
	pt.x = x;
	pt.y = y;
	ret = ::ClientToScreen(m_hWnd, &pt);
	outX = pt.x;
	outY = pt.y;
	return ret;
}

BOOL CBaseWnd::GetWindowText(WCHAR* lpstring, int nMaxCount)
{
	if (m_hWnd == 0)
		return FALSE;
	return ::GetWindowText(m_hWnd, lpstring, nMaxCount);
}
int CBaseWnd::GetWindowTextLength()
{
	if (m_hWnd == 0)
		return 0;
	return ::GetWindowTextLength(m_hWnd);
}
BOOL CBaseWnd::MoveWindow(int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
{
	if (m_hWnd == 0)
		return FALSE;
	return ::MoveWindow(m_hWnd, X, Y, nWidth, nHeight, bRepaint);
}
long CBaseWnd::SetParent(long parentHwnd)
{
	if (m_hWnd == 0)
		return 0;
	
	return (long)::SetParent(m_hWnd, (HWND)parentHwnd);
}
long CBaseWnd::GetParent()
{
	if (m_hWnd == 0)
		return 0;
	return (long) ::GetParent(m_hWnd);
}
BOOL CBaseWnd::CloseWindow()
{
	if (m_hWnd == NULL)
		return FALSE;
	return ::CloseWindow(m_hWnd);
}

BOOL CBaseWnd::UpdateWindow()
{
	if (m_hWnd == NULL)
		return FALSE;
	return ::UpdateWindow(m_hWnd);
}

BOOL CBaseWnd::RedrawWindow(const RECT* lprcUpdate, long hrgn, UINT flags)
{
	if (m_hWnd == NULL)
		return FALSE;
	return ::RedrawWindow(m_hWnd, lprcUpdate, (HRGN)hrgn, flags);
}
LONG CBaseWnd::SetWindowStyle(LONG wStyle)
{
	if (m_hWnd == NULL)
		return FALSE;

	return SetWindowLong(m_hWnd, GWL_STYLE, wStyle);
}
BOOL CBaseWnd::SetLayeredWindowAttributes(float alpha)
{	
	if (m_hWnd == NULL)
		return FALSE;
	BYTE bAlpha = alpha*255;
	BOOL ret = ::SetLayeredWindowAttributes(m_hWnd, 0, bAlpha, LWA_ALPHA);

	return ret;
}

BOOL CBaseWnd::SetCursor(WCHAR* strCursor)
{
	if (wcscmp(strCursor, L"arrow") == 0)
	{
		m_hCurrentCursor = m_hArror;
	}
	else if (wcscmp(strCursor, L"cross") == 0)
	{
		m_hCurrentCursor = m_hCross;
	}
	else if (wcscmp(strCursor, L"hand") == 0)
	{
		m_hCurrentCursor = m_hHand;
	}	
	else if (wcscmp(strCursor,  L"drop") == 0)
	{
		m_hCurrentCursor = m_hDrop;
	}
	else if (wcscmp(strCursor,  L"query") == 0)
	{
		m_hCurrentCursor = m_hQuery;
	}
	else if (wcscmp(strCursor,  L"size ns") == 0)
	{
		m_hCurrentCursor = m_hSizeNS;
	}
	else if (wcscmp(strCursor,  L"size we") == 0)
	{
		m_hCurrentCursor = m_hSizeWE;
	}
	else if (wcscmp(strCursor,  L"size nwse") == 0)
	{
		m_hCurrentCursor = m_hSizeNWSE;
	}
	else if (wcscmp(strCursor,  L"size nesw") == 0)
	{
		m_hCurrentCursor = m_hSizeNESW;
	}
	else if (wcscmp(strCursor,  L"size all") == 0)
	{
		m_hCurrentCursor = m_hSizeAll;
	}
	else if (m_mapCursors.find(strCursor) != m_mapCursors.end())
	{
		m_hCurrentCursor = m_mapCursors[strCursor];
	}
	else
	{
		return false;
	}
	::SetCursor(m_hCurrentCursor);
	return TRUE;
}
BOOL CBaseWnd::LoadCursor(const WCHAR* name, const WCHAR* filename)
{
	HCURSOR hCur = ::LoadCursorFromFile(filename);
	if(hCur)
		m_mapCursors[name] = hCur;
	return hCur != NULL;
}
void CBaseWnd::SetCapture(BOOL bCapture)
{
	if( m_hWnd && bCapture)
		::SetCapture(m_hWnd);
	else
		::ReleaseCapture();
}
BOOL CBaseWnd::EnableWindow(BOOL bEnable)
{
	if(!m_hWnd)
		return FALSE;
	return ::EnableWindow(m_hWnd, bEnable);
}
BOOL CBaseWnd::SetFocus()
{
	if(!m_hWnd)
		return FALSE;
	HWND hwndLastFocus = ::SetFocus(m_hWnd);
	return TRUE;
}

void CBaseWnd::EnterMovingMode()
{
	if (!m_bFullScreen)
	{
		::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
	}
}

LRESULT CBaseWnd::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT lr = S_OK;
	BOOL bCallDefault = TRUE;
	switch (message)
	{
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_MBUTTONDBLCLK:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
	case WM_RBUTTONDBLCLK:
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_LBUTTONDBLCLK:
	case WM_MOUSEMOVE:
	case WM_MOUSEWHEEL:
		if (!m_isMouseInWindow)
		{
			m_isMouseInWindow = TRUE;
			_TrackMouseLeave();
		}
		lr = _OnMouseMessage(message, wParam, lParam);
		break;
	case WM_MOUSELEAVE:
		m_isMouseInWindow = FALSE;
		lr = _OnMouseMessage(message, wParam, lParam);
		break;
	case WM_SYSKEYDOWN:
		lr = _OnKeyboardMessage(message, wParam, lParam);
		bCallDefault = FALSE;
		break;
	case WM_CHAR:
	case WM_KEYDOWN:
	case WM_KEYUP:
		lr = _OnKeyboardMessage(message, wParam, lParam);
		break;

	case WM_ACTIVATE:
		lr = _OnActivate(message, wParam, lParam);
		break;
	case WM_ACTIVATEAPP:
		lr = _OnActivateApp(message, wParam, lParam);
		break;
	case WM_CLOSE:
		lr = OnClose();
		break;

	case WM_PAINT:
		lr = OnPaint();
		break;
	
	case WM_ERASEBKGND:
		bCallDefault = FALSE;
		break;

	case WM_CREATE:
		lr = _OnCreate(message, wParam, lParam);
		break;
	case WM_DESTROY:
		lr = OnDestory();
		break;
	case WM_ENABLE:
		lr = _OnEnable(message, wParam, lParam);
		break;
	case WM_ENTERSIZEMOVE:
		lr = OnEnterSizeMove();
		break;
	case WM_EXITSIZEMOVE:
		lr = OnExitSizeMove();
		break;
	case WM_GETMINMAXINFO:
		lr = _OnGetMinMaxInfo(message, wParam, lParam);
		break;
	case WM_MOVE:
		lr = _OnMove(message, wParam, lParam);
		break;
	case WM_MOVING:
		lr = _OnMoving(message, wParam, lParam);
		break;
	case WM_NCACTIVATE:
		lr = _OnNCActivate(message, wParam, lParam);
		break;
	
	case WM_NCCREATE:
		lr = _OnNCCreate(message, wParam, lParam);
		break;
	case WM_NCDESTROY:
		lr = OnNCDestory();
		break;
	case WM_NULL:
		lr = OnNullMessage();
		break;
	case WM_QUIT:
		lr = _OnQuit(message, wParam, lParam);
		break;
	case WM_CANCELMODE:
		lr = OnCancelMode();
		break;
	case WM_QUERYDRAGICON:
		lr = OnQueryDragIcon();
		break;
	case WM_QUERYOPEN:
		lr = OnQueryOpen();
		break;
	case WM_SHOWWINDOW:
		lr = _OnShowWindow(message, wParam, lParam);
		break;
	case WM_SIZE:
		lr = _OnSize(message, wParam, lParam);
		break;
	case WM_SIZING:
		lr = _OnSizing(message, wParam, lParam);
		break;
	case WM_STYLECHANGED:
		lr = _OnStyleChanged(message, wParam, lParam);
		break;
	case WM_STYLECHANGING:
		lr = _OnStyleChanging(message, wParam, lParam);
		break;
	case WM_THEMECHANGED:
		lr = OnThemeChanged();
		break;
	case WM_USERCHANGED:
		lr = OnUserChanged();
		break;
	case WM_WINDOWPOSCHANGED:
		lr = _OnWindowPosChanged(message, wParam, lParam);
		bCallDefault = FALSE;
		break;
	case WM_WINDOWPOSCHANGING:
		lr = _OnWindowPosChanging(message, wParam, lParam);
		break;
	case WM_SETCURSOR:
		if (m_hCurrentCursor != m_hArror)
		{
			bCallDefault = FALSE;
		}
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	if (bCallDefault)
	{
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	else
	{
		return 0;
	}
}

LRESULT CBaseWnd::_OnMouseMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT ret = 0;
	int xPos = GET_X_LPARAM(lParam);
	int yPos = GET_Y_LPARAM(lParam);
	int fwKeys = GET_KEYSTATE_WPARAM(wParam);
	int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);

	int dx = xPos - m_preMouseX;
	int dy = yPos - m_preMouseY;

	ret = this->OnMouseMessage(message, xPos, yPos, dx, dy, zDelta, fwKeys);

	m_preMouseX = xPos;
	m_preMouseY = yPos;
	
	return ret;
	
}
LRESULT CBaseWnd::OnMouseMessage(UINT message, int x, int y, int dx, int dy, int zDelta, int keyState)
{
	return 1;
}

LRESULT CBaseWnd::OnKeyboardMessage(UINT message, UINT nChar, UINT nRepCnt)
{
	return 1;
}

LRESULT CBaseWnd::_OnKeyboardMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	UINT nChar = wParam;
	UINT nRetCnt = lParam & 0x0000FFFF;
	return this->OnKeyboardMessage(message, nChar, nRetCnt);
}

LRESULT CBaseWnd::OnActivate(UINT actType, BOOL bMinimize, long hwnd)
{
	return 1;
}
LRESULT CBaseWnd::_OnActivate(UINT message, WPARAM wParam, LPARAM lParam)
{
	int actType = LOWORD(wParam); //WA_ACTIVE, WA_CLICKACTIVE2 or WA_INACTIVE 
	int bMinimize = HIWORD(wParam);
	long hWnd = (long)lParam;
	return OnActivate(actType, bMinimize, hWnd);

}
LRESULT CBaseWnd::OnActivateApp(BOOL bActivate, long hThread)
{
	return 1;
}
LRESULT CBaseWnd::_OnActivateApp(UINT message, WPARAM wParam, LPARAM lParam)
{
	BOOL bActivate = wParam; 
	long hThread = (long)lParam;
	return this->OnActivateApp(bActivate, hThread);
}

LRESULT CBaseWnd::OnClose()
{
	return 1;
}
LRESULT CBaseWnd::OnPaint()
{
	return 1;
}
LRESULT CBaseWnd::OnCreate(CREATESTRUCT* pCreateInfo)
{
	return 1;
}
LRESULT CBaseWnd::_OnCreate(UINT message, WPARAM wParam, LPARAM lParam)
{
	CREATESTRUCT* pCreateInfo = (CREATESTRUCT*)lParam;
	return OnCreate(pCreateInfo);
}
LRESULT CBaseWnd::OnDestory()
{
	return 1;
}
LRESULT CBaseWnd::OnEnable(BOOL bEnable)
{
	return 1;
}
LRESULT CBaseWnd::_OnEnable(UINT message, WPARAM wParam, LPARAM lParam)
{
	BOOL bEnable = (BOOL)wParam;
	return OnEnable(bEnable);
}
LRESULT CBaseWnd::OnEnterSizeMove()
{
	return 1;
}
LRESULT CBaseWnd::OnExitSizeMove()
{
	return 1;
}
LRESULT CBaseWnd::OnGetMinMaxInfo(MINMAXINFO* pInfo)
{
	return 1;
}
LRESULT CBaseWnd::_OnGetMinMaxInfo(UINT message, WPARAM wParam, LPARAM lParam)
{
	MINMAXINFO* pInfo = (MINMAXINFO*)lParam;
	return OnGetMinMaxInfo(pInfo);
}

LRESULT CBaseWnd::OnMove(int x, int y)
{
	return 1;
}

LRESULT CBaseWnd::_OnMove(UINT message, WPARAM wParam, LPARAM lParam)
{
	int xPos = (int)(short) LOWORD(lParam);   // horizontal position 
	int yPos = (int)(short) HIWORD(lParam);   // vertical position 
	return OnMove(xPos, yPos);
}

LRESULT CBaseWnd::OnMoving(RECT* prect)
{
	return 1;
}
LRESULT CBaseWnd::_OnMoving(UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT* pRect = (RECT*)lParam;
	return OnMoving(pRect);
}
LRESULT CBaseWnd::OnNCActivate(BOOL bActivate, long hRgn)
{
	return 1;
}

LRESULT CBaseWnd::_OnNCActivate(UINT message, WPARAM wParam, LPARAM lParam)
{
	BOOL bActivate = wParam;
	long hRgn = 0;
	if (lParam != -1)
	{
		hRgn = (long)lParam;
	}
	return OnNCActivate(bActivate, hRgn);
}

LRESULT CBaseWnd::OnNCCreate(CREATESTRUCT* pCreateInfo)
{
	return 1;
}
LRESULT CBaseWnd::_OnNCCreate(UINT message, WPARAM wParam, LPARAM lParam)
{
	CREATESTRUCT* pCreateInfo = (CREATESTRUCT*)lParam;
	return OnNCCreate(pCreateInfo);
}

LRESULT CBaseWnd::OnNCDestory()
{
	return 1;
}
LRESULT CBaseWnd::OnNullMessage()
{
	return 1;

}

LRESULT CBaseWnd::OnQuit(int nExitCode)
{
	return 1;
}
LRESULT CBaseWnd::_OnQuit(UINT message, WPARAM wParam, LPARAM lParam)
{
	int nExitCode = wParam;
	return OnQuit(nExitCode);
}
LRESULT CBaseWnd::OnCancelMode()
{
	return 1;
}


LRESULT CBaseWnd::OnQueryDragIcon()
{
	return 1;
}
LRESULT CBaseWnd::OnQueryOpen()
{
	return 1;
}
LRESULT CBaseWnd::OnShowWindow(BOOL bShow, UINT status)
{
	return 1;
}
LRESULT CBaseWnd::_OnShowWindow(UINT message, WPARAM wParam, LPARAM lParam)
{
	BOOL bShow = wParam;
	UINT status = lParam ;
	return OnShowWindow( bShow, status);
}
LRESULT CBaseWnd::OnSize(UINT width, UINT height, UINT nFlag)
{
	return 1;
}
LRESULT CBaseWnd::_OnSize(UINT message, WPARAM wParam, LPARAM lParam)
{
	UINT width = LOWORD(lParam);
	UINT height = HIWORD(lParam);
	UINT nFlag = wParam;
	return OnSize(width, height, nFlag);
}

LRESULT CBaseWnd::OnSizing(RECT* pRect, UINT nFlag)
{
	return 1;
}
LRESULT CBaseWnd::_OnSizing(UINT message, WPARAM wParam, LPARAM lParam)
{
	UINT flag = wParam;
	LPRECT pRect = (LPRECT)lParam;
	return OnSizing(pRect, flag);
}
LRESULT CBaseWnd::OnStyleChanged(int styleType, STYLESTRUCT* pStyleInfo)
{
	return 1;
}
LRESULT CBaseWnd::_OnStyleChanged(UINT message, WPARAM wParam, LPARAM lParam)
{
	int styleType = wParam;
	STYLESTRUCT* pStyleInfo = NULL;
	return OnStyleChanged(styleType, pStyleInfo);
}

LRESULT CBaseWnd::OnStyleChanging(int styleType, STYLESTRUCT* pStyleInfo)
{
	return 1;
}
LRESULT CBaseWnd::_OnStyleChanging(UINT message, WPARAM wParam, LPARAM lParam)
{
	int styleType = wParam;
	STYLESTRUCT* pStyleInfo = NULL;
	return OnStyleChanging(styleType, pStyleInfo);
}

LRESULT CBaseWnd::OnThemeChanged()
{
	return 1;
}
LRESULT CBaseWnd::OnUserChanged()
{
	return 1;
}
LRESULT CBaseWnd::OnWindowPosChanged(WINDOWPOS* pwndPos)
{
	return 1;
}
LRESULT CBaseWnd::_OnWindowPosChanged(UINT message, WPARAM wParam, LPARAM lParam)
{
	WINDOWPOS* pwndPos = (WINDOWPOS*)lParam;
	return OnWindowPosChanged(pwndPos);
}
LRESULT CBaseWnd::OnWindowPosChanging(WINDOWPOS* pwndPos)
{
	return 1;
}
LRESULT CBaseWnd::_OnWindowPosChanging(UINT message, WPARAM wParam, LPARAM lParam)
{
	WINDOWPOS* pwndPos = (WINDOWPOS*)lParam;
	return OnWindowPosChanging(pwndPos);
}

BOOL CBaseWnd::SetFullScreen(BOOL bFullScreen, BOOL bShow, BOOL bActivate)
{
	if (bFullScreen == m_bFullScreen)
		return TRUE;
	m_bFullScreen = bFullScreen;

    if(m_bFullScreen)
    {
        m_wpNormal.length = sizeof(WINDOWPLACEMENT);
        ::GetWindowPlacement(m_hWnd, &m_wpNormal);

		MONITORINFO mi;
		ZeroMemory(&mi, sizeof(MONITORINFO));
		mi.cbSize = sizeof(mi);
		GetMonitorInfo(
			MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST),
			&mi			
		);
		RECT& r = mi.rcMonitor;
		DWORD fullStyle = WINDOW_STYLE_FULLSCREEN;
		LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
		::SetWindowLong(m_hWnd, GWL_STYLE, fullStyle | (lStyle & WS_VISIBLE));
		::SetWindowPos(m_hWnd, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, (bShow ? SWP_SHOWWINDOW : 0) | (bActivate ? 0 : SWP_NOACTIVATE) | SWP_FRAMECHANGED );

		HMENU hMenu = GetSystemMenu(m_hWnd, FALSE);
		if( hMenu )
			::EnableMenuItem(hMenu, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
    }
    else
    {
		LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
		::SetWindowLong(m_hWnd, GWL_STYLE, m_winStyle | (lStyle & WS_VISIBLE));
		//::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, (show ? SWP_SHOWWINDOW : 0) | (activate ? 0 : SWP_NOACTIVATE) | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
		if (bShow)
			m_wpNormal.showCmd = bActivate ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
		else
			m_wpNormal.showCmd = (lStyle & WS_VISIBLE) ? SW_SHOWNOACTIVATE : SW_HIDE;
		::SetWindowPlacement(m_hWnd, &m_wpNormal);

		/*
		SetWindowPlacement: (MSDN)
		If the information specified in WINDOWPLACEMENT would result in a window that is completely off the screen,
		the system will automatically adjust the coordinates so that the window is visible,
		taking into account changes in screen resolution and multiple monitor configuration.
		*/

		HMENU hMenu = ::GetSystemMenu(m_hWnd, FALSE);
		if( hMenu )
			EnableMenuItem(hMenu, SC_MOVE, MF_BYCOMMAND);
    }
	return TRUE;
}
BOOL CBaseWnd::IsFullScreen()
{
	return m_bFullScreen;
}